package ru.spb.osll.myfit.fixtures.base;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MyFitGracefulNamer {
	private static Pattern DISGRACEFUL_NAME_PATTERN = Pattern
			.compile("\\w(?:[.]|\\w)*[^.]");
	public static String DELIMETER = "_";

	public static boolean isGracefulName(String fixtureName) {
		Matcher matcher = DISGRACEFUL_NAME_PATTERN.matcher(fixtureName);
		return !matcher.matches();
	}

	public static String disgrace(String fixtureName) {
		MyFitGracefulNamer namer = new MyFitGracefulNamer();

		for (int i = 0; i < fixtureName.length(); i++) {
			char c = Character.toLowerCase(fixtureName.charAt(i));
			if (Character.isLetter(c))
				namer.currentState.letter(c);
			else if (Character.isDigit(c))
				namer.currentState.digit(c);
			else
				namer.currentState.other(c);
		}

		return namer.finalName.toString();
	}

	private StringBuffer finalName = new StringBuffer();

	private GracefulNameState currentState = new InWordState();

	private MyFitGracefulNamer() {
	}

	private interface GracefulNameState {
		public void letter(char c);

		public void digit(char c);

		public void other(char c);
	}

	private class InWordState implements GracefulNameState {
		public void letter(char c) {
			finalName.append(c);
		}

		public void digit(char c) {
			finalName.append(DELIMETER);
			finalName.append(c);
			currentState = new InNumberState();
		}

		public void other(char c) {
			currentState = new OutOfWordState();
		}
	}

	private class InNumberState implements GracefulNameState {
		public void letter(char c) {
			finalName.append(DELIMETER);
			finalName.append(c);
			currentState = new InWordState();
		}

		public void digit(char c) {
			finalName.append(c);
		}

		public void other(char c) {
			currentState = new OutOfWordState();
		}
	}

	private class OutOfWordState implements GracefulNameState {
		public void letter(char c) {
			finalName.append(DELIMETER);
			finalName.append(c);
			currentState = new InWordState();
		}

		public void digit(char c) {
			finalName.append(DELIMETER);
			finalName.append(c);
			currentState = new InNumberState();
		}

		public void other(char c) {
		}
	}
}
